package cn.yikaojiuguo.student.support.utils;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.Xml;

import com.alipay.sdk.app.PayTask;
import com.tencent.mm.sdk.modelpay.PayReq;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;

import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;

import cn.yikaojiuguo.student.app.YiKaoApplication;
import cn.yikaojiuguo.student.bean.MessageEvent;
import cn.yikaojiuguo.student.support.simple.UrlConstants;
import cn.yikaojiuguo.student.support.volley.Response;
import de.greenrobot.event.EventBus;

/**
 * Created by cfan_yang on 2015/12/30.
 */
public class PayUtils {

    // 商户PID
    public static final String PARTNER = "2088801130109302";
    // 商户收款账号
    public static final String SELLER = "beours@126.com";
    // 商户私钥，pkcs8格式
    public static final String RSA_PRIVATE = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALsJfXpP851Y95xVub0qhaNSBFcVU0ALA6cGedbzAx+NTViRZ8cbXuppKv4Ail9H8F/NlSpYR/HVueSH9FLYurdgGSF1rDHBceppVcU4AjmTMhXJfvhAAU6RkYQVzTKmD6/jeA35CWeokKx/N76X93oufxlPAgHUEiXoUVP7w9zPAgMBAAECgYA3VmF3lLwhK7dm274uh6wuXA/IrBiLdDbKbhISVKfx596ge7TWpfR5KlB8AjDua9xkm/CsLJ5soK11Pfw9nr3vDYEVd9bGnpBcRZNeKEIjmor4es26cftb2B6OQ82gWFQXStMDnnTY4/ygXKAP0sKJ//a8eG+b7WvYwvQRZ5qLcQJBAOsO4r229nC2UQH9UX9I3Qwv285g7kLAP0/sNS8ufAQcbLsiRosJDNjIO300I1a4IFbmT673O2nNn9X+qAtKbGUCQQDLs1vHWVrTX6UMnxcEbKEX1aQHIQhh4zecV8bok03o18eD++psfXjS03Knpjsuamh2z7s+w4CPL3MnnwE7pq8jAkEA1yqmJdGQnzZUywRukJxLM/evNqiGEXZXvjpTqN/dSAoZAefrOSRMrTgFNKQAYUZk3AcxE9FegohmcoYMn2E9/QJAVQCfh+yNri73XPD2Ve5Ouvd331G1gcOjbSZj5qGxnTyOEVGKXYNua+u4qKUBhTj6JrpA1MwYVafjUeFUTmQcKQJAR5ET7p7joCsh7hTma9QI7xCWD2tmZj02d0Hh4msjYQhfYJIA25JUoBf5dhVbF7J+SCy1FnpoEMo1kWIuc1IB2w==";

    public static final int SDK_PAY_FLAG = 1;

    public static final int SDK_CHECK_FLAG = 2;

    private final static String tradeType = "APP";

    private static String orderPrice;
    private static String orderSubject;
    private static String orderNo;
    private static Map<String,String> resultunifiedorder;
    private static PayReq req;


    public static void payByWx(Context context, String gid, final String price, final String subject){

        if(!(YiKaoApplication.getWXAPI().isWXAppInstalled() && YiKaoApplication.getWXAPI().isWXAppSupportAPI())){//没有安装微信，不能进行微信支付
            ToastUtil.showToast(context,"请先安装微信");
            return;
        }
        if(!checkPrice(price)) {
            ToastUtil.showToast(context,"请输入正确的金额");
            return;
        }

        EventBus.getDefault().post(new MessageEvent("正在加载...", MessageEvent.MessageType.SHOW_PROGRESS_DIALOG));
        orderNo = getOutTradeNo();
        String requestUrl = null;
        try {
            requestUrl = UrlConstants.ADD_GOLD_ORDER + "&mid=" + YiKaoApplication.getUserId() +
                    "&gid=" + gid + "&username=" + URLEncoder.encode(YiKaoApplication.getUserName
                    (), "UTF-8") + "&ordid=" + orderNo;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        RequestUtil.requestGet(requestUrl, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                EventBus.getDefault().post(new MessageEvent(MessageEvent.MessageType
                        .DISMISS_PROGRESS_DIALOG));
                if (response != null && response.optBoolean("success")) {
                    orderPrice = price;
                    orderSubject = subject;
                    GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
                    getPrepayId.execute();
                } else {
                    EventBus.getDefault().post(new MessageEvent(MessageEvent.MessageType.BUTTON_PAY_ABLE));
                }
            }
        }, null, "PAY WX");
    }


    /**
     * 支付宝支付
     */
    public static void payByAli(final Context context, String gid, final String orderSubject, final String
            orderDetail, final String
            orderPrice, final Handler mHandler) {
        if(!checkPrice(orderPrice)) {
            ToastUtil.showToast(context,"请输入正确的金额");
            return;
        }
        EventBus.getDefault().post(new MessageEvent("正在加载...", MessageEvent.MessageType.SHOW_PROGRESS_DIALOG));
        orderNo = getOutTradeNo();
        String requestUrl = null;
        try {
            requestUrl = UrlConstants.ADD_GOLD_ORDER + "&mid=" + YiKaoApplication.getUserId() +
                    "&gid=" + gid + "&username=" + URLEncoder.encode(YiKaoApplication.getUserName
                    (), "UTF-8") + "&ordid=" + orderNo;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        RequestUtil.requestGet(requestUrl, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                EventBus.getDefault().post(new MessageEvent(MessageEvent.MessageType.DISMISS_PROGRESS_DIALOG));
                if(response!=null && response.optBoolean("success")) {
                    // 订单
                    String orderInfo = getOrderInfo(orderSubject, orderDetail, orderPrice, orderNo);
                    // 对订单做RSA 签名
                    String sign = sign(orderInfo);
                    try {
                        // 仅需对sign 做URL编码
                        sign = URLEncoder.encode(sign, "UTF-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }

                    // 完整的符合支付宝参数规范的订单信息
                    final String payInfo = orderInfo + "&sign=\"" + sign + "\"&"
                            + getSignType();

                    Runnable payRunnable = new Runnable() {

                        @Override
                        public void run() {
                            // 构造PayTask 对象
                            PayTask alipay = new PayTask((Activity) context);
                            // 调用支付接口，获取支付结果
                            String result = alipay.pay(payInfo);

                            Message msg = new Message();
                            msg.what = SDK_PAY_FLAG;
                            msg.obj = result;
                            mHandler.sendMessage(msg);
                        }
                    };

                    // 必须异步调用
                    Thread payThread = new Thread(payRunnable);
                    payThread.start();
                } else {
                    EventBus.getDefault().post(new MessageEvent(MessageEvent.MessageType.BUTTON_PAY_ABLE));
                }
            }
        }, null, "PAY ALI");
    }

    private static boolean checkPrice(String orderPrice) {
        try {
            Float.parseFloat(orderPrice);
        } catch (NumberFormatException e) {
            LogUtil.showErrorLog("order price must be number");
            return false;
        }
        return true;
    }

    /**
     * get the out_trade_no for an order. 生成商户订单号，该值在商户端应保持唯一（可自定义格式规范）
     */
    public static String getOutTradeNo() {
        SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss",
                Locale.getDefault());
        Date date = new Date();
        String key = format.format(date);

        Random r = new Random();
        key = key + r.nextInt();
        key = key.substring(0, 15);
        return key;
    }

    /**
     * create the order info. 创建订单信息
     *
     */
    public static String getOrderInfo(String subject, String body, String price, String orderNo) {

        // 签约合作者身份ID
        String orderInfo = "partner=" + "\"" + PARTNER + "\"";

        // 签约卖家支付宝账号
        orderInfo += "&seller_id=" + "\"" + SELLER + "\"";

        // 商户网站唯一订单号
        orderInfo += "&out_trade_no=" + "\"" + orderNo + "\"";

        // 商品名称
        orderInfo += "&subject=" + "\"" + subject + "\"";

        // 商品详情
        orderInfo += "&body=" + "\"" + body + "\"";

        // 商品金额
        orderInfo += "&total_fee=" + "\"" + price + "\"";

        // 服务器异步通知页面路径
        orderInfo += "&notify_url=" + "\"" + UrlConstants.PAY_NOTIFY_ALI
                + "\"";

        // 服务接口名称， 固定值
        orderInfo += "&service=\"mobile.securitypay.pay\"";

        // 支付类型， 固定值
        orderInfo += "&payment_type=\"1\"";

        // 参数编码， 固定值
        orderInfo += "&_input_charset=\"utf-8\"";

        // 设置未付款交易的超时时间
        // 默认30分钟，一旦超时，该笔交易就会自动被关闭。
        // 取值范围：1m～15d。
        // m-分钟，h-小时，d-天，1c-当天（无论交易何时创建，都在0点关闭）。
        // 该参数数值不接受小数点，如1.5h，可转换为90m。
        orderInfo += "&it_b_pay=\"30m\"";

        // extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付
        // orderInfo += "&extern_token=" + "\"" + extern_token + "\"";

        // 支付宝处理完请求后，当前页面跳转到商户指定页面的路径，可空
        orderInfo += "&return_url=\"m.alipay.com\"";

        // 调用银行卡支付，需配置此参数，参与签名， 固定值 （需要签约《无线银行卡快捷支付》才能使用）
        // orderInfo += "&paymethod=\"expressGateway\"";

        return orderInfo;
    }

    /**
     * sign the order info. 对订单信息进行签名
     *
     * @param content
     *            待签名订单信息
     */
    public static String sign(String content) {
        return SignUtils.sign(content, RSA_PRIVATE);
    }

    /**
     * get the sign type we use. 获取签名方式
     *
     */
    public static String getSignType() {
        return "sign_type=\"RSA\"";
    }

    static class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String,String>> {

        @Override
        protected void onPreExecute() {

        }

        @Override
        protected void onPostExecute(Map<String,String> result) {
            resultunifiedorder=result;
            Log.i("WXPAY", "result = " + result);
            if(tradeType.equals("APP")) { //需要调起微信支付
                genPayReq();
                sendPayReq();
            }

        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
        }

        @Override
        protected Map<String,String> doInBackground(Void... params) {

            String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
            String entity = genProductArgs();
            LogUtil.showInfoLog("WXPAY","entity = " + entity) ;
            byte[] buf = Util.httpPost(url, entity);

            String content = new String(buf);
            Map<String,String> xml=decodeXml(content);

            return xml;
        }
    }

    private static String genProductArgs() {
        StringBuffer xml = new StringBuffer();

        try {
            orderPrice = (int)(Float.parseFloat(orderPrice) * 100) + "";
            Log.i("WXPAY","orderPrice = " + orderPrice);
            String	nonceStr = genNonceStr();
            xml.append("</xml>");
            List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
            packageParams.add(new BasicNameValuePair("appid", YiKaoApplication.APP_ID));
            packageParams.add(new BasicNameValuePair("body", orderSubject));
            packageParams.add(new BasicNameValuePair("mch_id", YiKaoApplication.MCH_ID));
            packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
            packageParams.add(new BasicNameValuePair("notify_url", UrlConstants.WX_PAY_NOTIFY));
            packageParams.add(new BasicNameValuePair("out_trade_no",orderNo));
            packageParams.add(new BasicNameValuePair("spbill_create_ip","127.0.0.1"));
            packageParams.add(new BasicNameValuePair("total_fee", orderPrice));
            packageParams.add(new BasicNameValuePair("trade_type", tradeType));

            String sign = genPackageSign(packageParams);
            LogUtil.showInfoLog("WXPAY","sign = " + sign);
            packageParams.add(new BasicNameValuePair("sign", sign));


            String xmlstring =toXml(packageParams);
            xmlstring = new String(xmlstring.getBytes("UTF-8"), "ISO-8859-1");
            return xmlstring;

        } catch (Exception e) {
            return null;
        }
    }

    private static String genNonceStr() {
        Random random = new Random();
        return MD5Util.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    }

    /**
     生成签名
     */

    private static String genPackageSign(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(YiKaoApplication.API_KEY);

        String packageSign = MD5Util.getMessageDigest(sb.toString().getBytes()).toUpperCase();
        return packageSign;
    }

    private static String genAppSign(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(YiKaoApplication.API_KEY);

        String appSign = MD5Util.getMessageDigest(sb.toString().getBytes()).toUpperCase();
        return appSign;
    }

    private static String toXml(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        for (int i = 0; i < params.size(); i++) {
            sb.append("<"+params.get(i).getName()+">");


            sb.append(params.get(i).getValue());
            sb.append("</"+params.get(i).getName()+">");
        }
        sb.append("</xml>");
        return sb.toString();
    }

    public static Map<String,String> decodeXml(String content) {

        try {
            Map<String, String> xml = new HashMap<String, String>();
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(new StringReader(content));
            int event = parser.getEventType();
            while (event != XmlPullParser.END_DOCUMENT) {

                String nodeName=parser.getName();
                switch (event) {
                    case XmlPullParser.START_DOCUMENT:

                        break;
                    case XmlPullParser.START_TAG:

                        if("xml".equals(nodeName)==false){
                            //实例化student对象
                            xml.put(nodeName,parser.nextText());
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        break;
                }
                event = parser.next();
            }

            return xml;
        } catch (Exception e) {
        }
        return null;
    }

    private static void genPayReq() {
        req = new PayReq();
        req.appId = YiKaoApplication.APP_ID;
        req.partnerId = YiKaoApplication.MCH_ID;
        req.prepayId = resultunifiedorder.get("prepay_id");
        req.packageValue = "Sign=WXPay";
        req.nonceStr = genNonceStr();
        req.timeStamp = String.valueOf(genTimeStamp());
        List<NameValuePair> signParams = new LinkedList<NameValuePair>();
        signParams.add(new BasicNameValuePair("appid", req.appId));
        signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
        signParams.add(new BasicNameValuePair("package", req.packageValue));
        signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
        signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
        signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));
        req.sign = genAppSign(signParams);
    }
    private static void sendPayReq() {
        YiKaoApplication.getWXAPI().registerApp(YiKaoApplication.APP_ID);
        YiKaoApplication.getWXAPI().sendReq(req);
    }

    private static long genTimeStamp() {
        return System.currentTimeMillis() / 1000;
    }
}
